#ifndef RINGBUFFER_H_INCLUDED
#define RINGBUFFER_H_INCLUDED
#include <iostream>
#include <string.h>

using namespace std;

/**
*  ���ζ�����ģ��
*
*/
template <class T>
class RingBuffer
{
public:
	RingBuffer(int capacity);
	virtual ~RingBuffer();
	//���
	void Clear();
	//���
	bool PushItem(T element);
	//����
	bool PopItem(T &element);   //����һ��T�����ã�����Ӷ�ͷ�������Ƿ��ض�ͷ�������������ز�����������Ϻ������õ���ͷ
	//
	bool PopLastedItem(T &element);
	//�п�
	const bool isEmpty();
	//����
	const bool isFull();
	//�ӳ�
	const int length();
	//�ж�
	void printQueue(void(*pFunc)(T));    //��������ģ����Ĵ�ӡ������һ����Ӧ���͵Ĵ�ӡ����ָ��
private:
	//��������ָ��
	T * m_pQueue;
	//��������
	unsigned long m_iCapacity;
	//��ͷ
	unsigned long m_iHead;
	//��β
	unsigned long m_iTail;
};

template <class T>
RingBuffer<T>::RingBuffer(int capacity) {
	m_iCapacity = capacity;
	Clear();
	if ((m_pQueue = new T[m_iCapacity]) == NULL) {
		throw string("Queue Initialization Failed!");
	}
}

template <class T>
RingBuffer<T>::~RingBuffer() {
	delete[]m_pQueue;
	m_pQueue = NULL;
}

template <class T>
void RingBuffer<T>::Clear() 
{
	m_iHead = 0;
	m_iTail = 0;
}

template <class T>
bool RingBuffer<T>::PushItem(T element) 
{
	if (isFull()) {
		return false;
	}
	m_pQueue[m_iTail % m_iCapacity] = element;
	m_iTail++;
	return true;
}

template <class T>
bool RingBuffer<T>::PopItem(T &element) 
{
	if (isEmpty()) {
		return false;
	}
	//����һ��T�����ã�������ն�ͷ�������Ƿ���ͷ�������������ز�����������Ϻ������õ���ͷ
	element = m_pQueue[m_iHead % m_iCapacity];
	m_iHead++;
	return true;
}

template <class T>
bool RingBuffer<T>::PopLastedItem(T &element) 
{
	if (isEmpty())
	{
		return false;
	}
	m_iHead = m_iTail - 1;
	//����һ��T�����ã�������ն�ͷ�������Ƿ���ͷ�������������ز�����������Ϻ������õ���ͷ
	element = m_pQueue[m_iHead % m_iCapacity];
	m_iHead++;
	return true;
}

template <class T>
const bool RingBuffer<T>::isEmpty() 
{
	return m_iHead == m_iTail ? true : false;
}

template <class T>
const bool RingBuffer<T>::isFull() 
{
	return (m_iCapacity <= (m_iTail - m_iHead))? true : false;
}

template <class T>
const int RingBuffer<T>::length() 
{
	return m_iTail - m_iHead;
}

template <class T>
void RingBuffer<T>::printQueue(void(*pFunc)(T))
{
	for (int i = m_iHead; i < m_iTail; i++) 
	{
		pFunc(m_pQueue[i % m_iCapacity]);
	}
}
#endif // RINGBUFFER_H_INCLUDED
